package cat

import (
	"net/http"
	"strconv"

	"github.com/mars/pkg/loggers"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

const (
	transicationPt = "full"
	eventPt        = "info"
)

// CatTransEvent 通过日志进行埋点
// http://iwiki.pab.com.cn/pages/viewpage.action?pageId=17789998
type CatTransEvent struct {
	typeName string
	name     string
	status   int
}

func NewCatTransEvent(t string, name string) *CatTransEvent {
	return &CatTransEvent{
		typeName: t,
		name:     name,
		status:   http.StatusOK,
	}
}

func (t *CatTransEvent) SetStatusByResp(err error, resp *http.Response) *CatTransEvent {
	if err != nil || resp == nil {
		t.status = http.StatusInternalServerError
	} else {
		t.status = resp.StatusCode
	}
	return t
}

func (t *CatTransEvent) ReportError() *CatTransEvent {
	t.status = http.StatusInternalServerError
	return t
}

func (t *CatTransEvent) CompleteTransication(cost int64, extra []zap.Field, format string, args ...interface{}) {
	field, loggerLevel := t.buildCommonFiedsAndLoggerLevel(transicationPt, strconv.FormatInt(int64(cost), 10), extra)
	loggers.Instance().RawLogger().Log(loggerLevel, format, args, field)
}

func (t *CatTransEvent) CompleteTransicationWithFloat64(cost float64, extra []zap.Field, format string, args ...interface{}) {
	field, loggerLevel := t.buildCommonFiedsAndLoggerLevel(transicationPt, strconv.FormatFloat(cost, 'f', 3, 64), extra)
	loggers.Instance().RawLogger().Log(loggerLevel, format, args, field)
}

func (t *CatTransEvent) CompleteEvent(extra []zap.Field, format string, args ...interface{}) {
	field, loggerLevel := t.buildCommonFiedsAndLoggerLevel(eventPt, "", extra)
	loggers.Instance().RawLogger().Log(loggerLevel, format, args, field)
}

func (t *CatTransEvent) buildCommonFiedsAndLoggerLevel(pt string, cost string, extra []zap.Field) ([]zap.Field, zapcore.Level) {
	fileds := []zap.Field{
		zap.String("_pt", pt),
		zap.String("_t", t.typeName),
		zap.String("_n", t.name),
		zap.Int("_st", t.status),
	}

	if transicationPt == pt {
		fileds = append(fileds, zap.String("_rc", cost))
	}

	if len(fileds) > 0 {
		fileds = append(fileds, extra...)
	}

	var loggerLevel = zap.InfoLevel
	if t.status >= http.StatusBadRequest {
		loggerLevel = zap.ErrorLevel
	}

	return fileds, loggerLevel
}
